home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / utils / file / logiso.000 / logiso / RCS / dir.c,v next >
Encoding:
Text File  |  1995-03-24  |  7.3 KB  |  324 lines

  1. head    1.4;
  2. access;
  3. symbols
  4.     VER_0_3:1.4
  5.     VER_0_2:1.3;
  6. locks; strict;
  7. comment    @ * @;
  8.  
  9.  
  10. 1.4
  11. date    95.03.24.11.44.17;    author coulter;    state Exp;
  12. branches;
  13. next    1.3;
  14.  
  15. 1.3
  16. date    95.03.10.02.43.06;    author coulter;    state Exp;
  17. branches;
  18. next    1.2;
  19.  
  20. 1.2
  21. date    95.02.13.20.56.00;    author coulter;    state Exp;
  22. branches;
  23. next    1.1;
  24.  
  25. 1.1
  26. date    95.02.11.13.13.24;    author coulter;    state Exp;
  27. branches;
  28. next    ;
  29.  
  30.  
  31. desc
  32. @isofs directory handling functions.  Will add call to iso_ioctl.
  33. @
  34.  
  35.  
  36. 1.4
  37. log
  38. @Checkin version for 0.3 distribution.
  39. @
  40. text
  41. @/*
  42.  *  linux/fs/isofs/dir.c
  43.  * 
  44.  *  Copyright 1995 Michael Coulter for access logging.
  45.  *
  46.  *  (C) 1992, 1993, 1994  Eric Youngdale Modified for ISO9660 filesystem.
  47.  *
  48.  *  (C) 1991  Linus Torvalds - minix filesystem
  49.  *
  50.  *  isofs directory handling functions
  51.  */
  52.  
  53. #include <linux/errno.h>
  54.  
  55. #include <asm/segment.h>
  56.  
  57. #include <linux/fs.h>
  58. #include <linux/iso_fs.h>
  59. #include <linux/kernel.h>
  60. #include <linux/stat.h>
  61. #include <linux/string.h>
  62. #include <linux/mm.h>
  63. #include <linux/malloc.h>
  64. #include <linux/sched.h>
  65. #include <linux/locks.h>
  66.  
  67. #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
  68. #define ROUND_UP(x) (((x)+3) & ~3)
  69.  
  70. static int isofs_readdir(struct inode *, struct file *, struct dirent *, int);
  71.  
  72. static struct file_operations isofs_dir_operations = {
  73.     NULL,            /* lseek - default */
  74.     NULL,            /* read */
  75.     NULL,            /* write - bad */
  76.     isofs_readdir,        /* readdir */
  77.     NULL,            /* select - default */
  78.     iso_ioctl,        /* ioctl */
  79.     NULL,            /* no special open code */
  80.     NULL,            /* no special release code */
  81.     NULL            /* fsync */
  82. };
  83.  
  84. /*
  85.  * directories can handle most operations...
  86.  */
  87. struct inode_operations isofs_dir_inode_operations = {
  88.     &isofs_dir_operations,    /* default directory file-ops */
  89.     NULL,          /* create */
  90.     isofs_lookup,        /* lookup */
  91.     NULL,                /* link */
  92.     NULL,               /* unlink */
  93.     NULL,               /* symlink */
  94.     NULL,               /* mkdir */
  95.     NULL,            /* rmdir */
  96.     NULL,            /* mknod */
  97.     NULL,            /* rename */
  98.     NULL,            /* readlink */
  99.     NULL,            /* follow_link */
  100.     isofs_bmap,        /* bmap */
  101.     NULL,            /* truncate */
  102.     NULL            /* permission */
  103. };
  104.  
  105. static int isofs_readdir(struct inode * inode, struct file * filp,
  106.     struct dirent * dirent, int count)
  107. {
  108.     unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
  109.     unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
  110.     unsigned int block,offset,i, j;
  111.     char c = 0;
  112.     int inode_number;
  113.     struct buffer_head * bh;
  114.     void * cpnt = NULL;
  115.     unsigned int old_offset;
  116.     int dlen, rrflag;
  117.     char * dpnt, *dpnt1;
  118.     struct iso_directory_record * de;
  119.     
  120.     iso_log_add(inode->i_ino, inode->i_dev, ISO_LOG_OP_isofs_readdir);
  121.     dpnt1 = NULL;
  122.     if (!inode || !S_ISDIR(inode->i_mode))
  123.         return -EBADF;
  124.     
  125.     offset = filp->f_pos & (bufsize - 1);
  126.     block = isofs_bmap(inode,filp->f_pos>>bufbits);
  127.  
  128.     if(!block) return 0;
  129.  
  130.     if(!(bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size)))
  131.       return 0;
  132.  
  133.     while (filp->f_pos < inode->i_size) {
  134. #ifdef DEBUG
  135.         printk("Block, offset: %x %x %x\n",
  136.                block, offset, filp->f_pos);
  137. #endif
  138.         de = (struct iso_directory_record *) (bh->b_data + offset);
  139.         inode_number = (block << bufbits) + (offset & (bufsize - 1));
  140.         
  141.         /* If the length byte is zero, we should move on to the next
  142.            CDROM sector.  If we are at the end of the directory, we
  143.            kick out of the while loop. */
  144.         
  145.         if (*((unsigned char *) de) == 0)  {
  146.             brelse(bh);
  147.             offset = 0;
  148.             filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
  149.                        + ISOFS_BLOCK_SIZE);
  150.             block = isofs_bmap(inode,(filp->f_pos)>>bufbits);
  151.             if (!block
  152.                 || !(bh = breada(inode->i_dev, block, bufsize, filp->f_pos, 
  153.                          inode->i_size)))
  154.                 return 0;
  155.             continue;
  156.         }
  157.  
  158.         /* Make sure that the entire directory record is in the
  159.            current bh block.
  160.            If not, we malloc a buffer, and put the two halves together,
  161.            so that we can cleanly read the block */
  162.  
  163.         old_offset = offset;
  164.         offset += *((unsigned char *) de);
  165.         filp->f_pos += *((unsigned char *) de);
  166.  
  167.         if (offset >=  bufsize) {
  168.                 unsigned int frag1;
  169.             frag1 = bufsize - old_offset;
  170.             cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL);
  171.             memcpy(cpnt, bh->b_data + old_offset, frag1);
  172.             de = (struct iso_directory_record *) ((char *)cpnt);
  173.             brelse(bh);
  174.             offset = filp->f_pos & (bufsize - 1);
  175.             block = isofs_bmap(inode,(filp->f_pos)>> bufbits);
  176.             if (!block
  177.                 || !(bh = breada(inode->i_dev, block, bufsize,
  178.                          filp->f_pos, inode->i_size))) {
  179.                     kfree(cpnt);
  180.                 return 0;
  181.             };
  182.             memcpy((char *)cpnt+frag1, bh->b_data, offset);
  183.         }
  184.         
  185.         /* Handle the case of the '.' directory */
  186.  
  187.         rrflag = 0;
  188.         i = 1;
  189.         if (de->name_len[0] == 1 && de->name[0] == 0) {
  190.             put_fs_byte('.',dirent->d_name);
  191.             inode_number = inode->i_ino;
  192.             dpnt = ".";
  193.         }
  194.         
  195.         /* Handle the case of the '..' directory */
  196.         
  197.         else if (de->name_len[0] == 1 && de->name[0] == 1) {
  198.             put_fs_byte('.',dirent->d_name);
  199.             put_fs_byte('.',dirent->d_name+1);
  200.             i = 2;
  201.             dpnt = "..";
  202.             if((inode->i_sb->u.isofs_sb.s_firstdatazone
  203.                 << bufbits) != inode->i_ino)
  204.                 inode_number = inode->u.isofs_i.i_backlink;
  205.             else
  206.                 inode_number = inode->i_ino;
  207.             
  208.             /* This should never happen, but who knows.  Try to be forgiving */
  209.             if(inode_number == -1) {
  210.                 inode_number = 
  211.                     isofs_lookup_grandparent(inode,
  212.                          find_rock_ridge_relocation(de, inode));
  213.                 if(inode_number == -1){ /* Should never happen */
  214.                     printk("Backlink not properly set.\n");
  215.                     goto out;
  216.                 };
  217.             }
  218.         }
  219.         
  220.         /* Handle everything else.  Do name translation if there
  221.            is no Rock Ridge NM field. */
  222.         
  223.         else {
  224.             dlen = de->name_len[0];
  225.             dpnt = de->name;
  226.             i = dlen;
  227.             rrflag = get_rock_ridge_filename(de, &dpnt, &dlen, inode);
  228.             if (rrflag) {
  229.               if (rrflag == -1) {  /* This is a rock ridge reloc dir */
  230.                 if (cpnt) {
  231.                 kfree(cpnt);
  232.                 cpnt = NULL;
  233.                 };
  234.                 continue;
  235.               };
  236.               i = dlen;
  237.             }
  238.             else
  239.               if(inode->i_sb->u.isofs_sb.s_mapping == 'n') {
  240.                 dpnt1 = dpnt;
  241.                 dpnt = kmalloc(dlen, GFP_KERNEL);
  242.                 for (i = 0; i < dlen && i < NAME_MAX; i++) {
  243.                   if (!(c = dpnt1[i])) break;
  244.                   if (c >= 'A' && c <= 'Z') c |= 0x20;  /* lower case */
  245.                   if (c == '.' && i == dlen-3 && de->name[i+1] == ';' && de->name[i+2] == '1')
  246.                 break;  /* Drop trailing '.;1' (ISO9660:1988 7.5.1 requires period) */
  247.                   if (c == ';' && i == dlen-2 && de->name[i+1] == '1') 
  248.                 break;  /* Drop trailing ';1' */
  249.                   if (c == ';') c = '.';  /* Convert remaining ';' to '.' */
  250.                   dpnt[i] = c;
  251.                 }
  252.               }
  253.             for(j=0; j<i; j++)
  254.               put_fs_byte(dpnt[j],j+dirent->d_name); /* And save it */
  255.             if(dpnt1) {
  256.               kfree(dpnt);
  257.               dpnt = dpnt1;
  258.             }
  259.             
  260.             dcache_add(inode, dpnt, i, inode_number);
  261.               };
  262. #if 0
  263.         printk("Nchar: %d\n",i);
  264. #endif
  265.  
  266.         if (rrflag) kfree(dpnt);
  267.         if (cpnt) {
  268.             kfree(cpnt);
  269.             cpnt = NULL;
  270.         };
  271.         
  272.         if (i) {
  273.             put_fs_long(inode_number, &dirent->d_ino);
  274.             put_fs_byte(0,i+dirent->d_name);
  275.             put_fs_word(i,&dirent->d_reclen);
  276.             brelse(bh);
  277.             return ROUND_UP(NAME_OFFSET(dirent) + i + 1);
  278.         }
  279.           }
  280.     /* We go here for any condition we cannot handle.  We also drop through
  281.        to here at the end of the directory. */
  282.  out:
  283.     if (cpnt)
  284.         kfree(cpnt);
  285.     brelse(bh);
  286.     return 0;
  287. }
  288.  
  289.  
  290.  
  291. @
  292.  
  293.  
  294. 1.3
  295. log
  296. @Checkin files modified to make version 0.2
  297. @
  298. text
  299. @d3 2
  300. @
  301.  
  302.  
  303. 1.2
  304. log
  305. @Checkin working version.  Try to make it dynamic now.
  306. @
  307. text
  308. @d78 1
  309. a78 1
  310.     iso_log_add(inode->i_ino, ISO_LOG_OP_isofs_readdir);
  311. @
  312.  
  313.  
  314. 1.1
  315. log
  316. @Initial revision
  317. @
  318. text
  319. @d36 1
  320. a36 1
  321.     NULL,            /* ioctl - default */
  322. d78 1
  323. @
  324.